package cn.com.cis.service;

import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;

import cn.com.cis.domain.JobConfig;
import cn.com.cis.plugins.quartz.ETLJobListener;
import cn.com.cis.plugins.quartz.QrtzJobFactory;

@Service
public class QrtzJobService {

	@Autowired
	private SchedulerFactoryBean schedulerFactory;
	
	@Autowired
	private JobConfigService jobService;
    
    @Autowired
    private UserService userService;
    
	/**
	 * 加载定时作业。系统启动会被加载一次。
	 * 
	 * @throws SchedulerException
	 */
	@PostConstruct
	public void loadTask() throws SchedulerException {
		
		// 初始化job
		QrtzJobFactory.setUserService(userService);
		
		Scheduler scheduler = schedulerFactory.getScheduler();
		
		ETLJobListener listener = new ETLJobListener();
		listener.setJobConfigService(jobService);
		scheduler.getListenerManager().addJobListener(listener);
		
		// 获取任务信息数据
		List<JobConfig> jobList = jobService.queryAllJobs(0, 0);
		for (JobConfig job : jobList) {
			addOrUpdateScheduleJob(job);
		}
		
		scheduler.start();
	}
	
	public void addOrUpdateScheduleJob(JobConfig jobConfig) throws SchedulerException {
		Scheduler scheduler = schedulerFactory.getScheduler();
		// 停用状态的定时任务，不作处理
		if (!jobConfig.isEnable()) {
			return;
		}

		TriggerKey triggerKey = TriggerKey.triggerKey("job" + jobConfig.getJobId(), jobConfig.getJobGroup());

		CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
		
		// 不存在，创建一个
		if (null == trigger) {
			JobDetail jobDetail = JobBuilder.newJob(QrtzJobFactory.class)
					.withIdentity("job" + jobConfig.getJobId(), jobConfig.getJobGroup()).build();

			// TODO
			jobDetail.getJobDataMap().put(JobConfig.SCHEDULE_JOB_NAME_KEY, jobConfig);

			// 表达式调度构建器
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(jobConfig.getCronExpression());
			// 按新的cronExpression表达式构建一个新的trigger
			trigger = TriggerBuilder.newTrigger().withIdentity("job" + jobConfig.getJobId(), jobConfig.getJobGroup())
					.withSchedule(scheduleBuilder).build();
			Date ft = scheduler.scheduleJob(jobDetail, trigger);
			
			jobConfig.setJobStatus(2);
			jobConfig.setNextExecuteTime(ft);
			jobService.updateJobConfig(jobConfig);
		} else {
			// Trigger已存在，那么更新相应的定时设置
			// 表达式调度构建器
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(jobConfig.getCronExpression());
			// 按新的cronExpression表达式重新构建trigger
			trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
			// 按新的trigger重新设置job执行
			Date ft = scheduler.rescheduleJob(triggerKey, trigger);
			
			jobConfig.setJobStatus(2);
			jobConfig.setNextExecuteTime(ft);
			jobService.updateJobConfig(jobConfig);
		}

	}
	
	/**
	 * 立刻启用定时任务
	 * 
	 * @param jobConfig
	 *            定时任务描述信息
	 * @throws SchedulerException
	 */
	public void immediateExecutorJob(JobConfig jobConfig) throws SchedulerException {
		addOrUpdateScheduleJob(jobConfig);
		makeNewConfigWork();
	}
	
	private void makeNewConfigWork() throws SchedulerException{
		Scheduler scheduler = schedulerFactory.getScheduler();
		if (!scheduler.isShutdown()) {  
			scheduler.start();  
        }
	}
	
	/**
	 * 启用定时任务
	 * 
	 * @param jobConfig
	 *            定时任务描述信息
	 * @throws SchedulerException
	 */
	public void makeJobScheduled(JobConfig jobConfig) throws SchedulerException {
		addOrUpdateScheduleJob(jobConfig);
	}
	
	public void unscheduleJob(JobConfig jobConfig) throws SchedulerException {
		Scheduler scheduler = schedulerFactory.getScheduler();
		TriggerKey triggerKey = TriggerKey.triggerKey("job" + jobConfig.getJobId(), jobConfig.getJobGroup());
		scheduler.unscheduleJob(triggerKey);
		
		makeNewConfigWork();
	}
	
	/**
	 * 删除任务
	 * 
	 * @param jobConfig
	 *            定时任务描述信息
	 * @throws SchedulerException
	 */
	public void deleteJob(JobConfig jobConfig) throws SchedulerException {
		Scheduler scheduler = schedulerFactory.getScheduler();
		JobKey jobKey = JobKey.jobKey("job" + jobConfig.getJobId(), jobConfig.getJobGroup());
		TriggerKey triggerKey = TriggerKey.triggerKey("job" + jobConfig.getJobId(), jobConfig.getJobGroup());
		
		scheduler.pauseTrigger(triggerKey);    // 停止触发器 
		scheduler.unscheduleJob(triggerKey);   // 移除触发器
		scheduler.deleteJob(jobKey);           // 删除任务
		
		makeNewConfigWork();
	}

}
